package domain;

import astar.AStar;
import domain.Game.action;
import domain.exceptions.CannotMoveThereException;
import java.util.LinkedList;
import java.util.Vector;
import miniMax.MiniMax;

/**
 *
 * @author shai
 */
public class AgentSmart extends Agent{

	private LinkedList<action> _actionsPath;

	public AgentSmart(String name, Game.action lastDirection, String assinment){
		super(name, lastDirection, assinment);
		this._actionsPath = new LinkedList<action>();
	}
	
	public AgentSmart(AgentSmart other) {
		super(other);
		this._actionsPath = other._actionsPath;
	}

	@Override
	public void play(Board board, Vector<Agent> agents, int maxSteps){
		if (!this.isDead()){
		if(this._actionsPath.isEmpty()){
			// This branch will happen after reaching a flag.
			System.out.println("Actions Path is Empty ---> Creating action path");
			if (getAssignment().equals("1")){
				thinkAStar();
			} else if (getAssignment().equals("2.1")){
				thinkMiniMax(maxSteps);
			} else if (getAssignment().equals("2.2")){
				thinkMaxiMax(maxSteps);
			} else if (getAssignment().equals("2.3")){
				thinkExpectiMiniMax(maxSteps);
			}
			System.out.println("Smart Agent: \"I want to go: "+_actionsPath + "\"");
		}
		Game.action act = this._actionsPath.poll();
		try {
			act(act, board, agents);
		} catch (CannotMoveThereException ex) {
			Debug.println(ex.getMessage());
		}
		}
		else{
			System.out.println("I'm dead");
		}
	}

	private void thinkAStar() {
		AStar aStar = new AStar(this);
		this._actionsPath = aStar.runAStarSearch(Game._board, Game.getAgents(), Game._board.getFlags());
	}

	private void thinkMiniMax(int maxSteps) {
		MiniMax miniMax = new MiniMax(this, Game.getOtherPlayer(this));
		boolean withCutOff = true;
		this._actionsPath = miniMax.runMiniMaxSearch(Game._board, Game.getAgents(), Game._board.getFlags(), maxSteps, withCutOff);
	}

	private void thinkMaxiMax(int maxSteps) {
		Agent good 	= this;
		Agent bad	= Game.getOtherPlayer(this);
		MiniMax miniMax = new MiniMax(good, bad);
		this._actionsPath = miniMax.runMaxiMaxSearch(Game._board, Game.getAgents(), Game._board.getFlags(), maxSteps);
	}

	private void thinkExpectiMiniMax(int maxSteps) {
		MiniMax miniMax = new MiniMax(this, Game.getOtherPlayer(this));
		double probability = Game.PROBABILITY;
		this._actionsPath = miniMax.runExpectiMiniMaxSearch(Game._board, Game.getAgents(), Game._board.getFlags(), maxSteps, probability );
	}

}